package com.meshnetics.gb.event;

import com.meshnetics.gb.Context;
import com.meshnetics.gb.util.ToStringUtil;

/**
 * Parent for all events in the system.
 *
 * @author mmarkov
 */
public class Event {
    /** EventType of this Event. */
    protected EventType type;

    /** Name of this Event. */
    protected String name;

    /** Context of this Event. */
    protected Context ctx;

    /**
     * Constructs Event from the given name, type and having no additional parameters (Context).
     *
     * @param name name of the Event
     * @param type EventType of the Event
     * @throws IllegalArgumentException if the given type is a composite one
     */
    public Event(String name, EventType type) {
        this(name, type, null);
    }

    /**
     * Constructs Event from the given name and type.
     *
     * @param name name of the Event
     * @param type EventType of the Event
     * @param ctx Context of the Event (could be null)
     * @throws IllegalArgumentException if the given type is a composite one
     */
    public Event(String name, EventType type, Context ctx) {
        this.name = name;

        if (type.isComposite()) {
            throw new IllegalArgumentException("Event should not have a composite type");
        }
        this.type = type;
        this.ctx = ctx;
    }

    /**
     * Returns the EventType of this Event.
     *
     * @return the EventType of this Event
     */
    public EventType getEventType() {
        return type;
    }

    /**
     * Returns the name of this Event.
     *
     * @return the name of this Event
     */
    public String getName() {
        return name;
    }

    /**
     * Returns the parameters of this Event (Context).
     *
     * @return the Context of this Event
     */
    public Context getContext() {
        return ctx;
    }

    /**
     * Returns a hash code of this Event.
     *
     * @return a hash code of this Event
     */
    public int hashCode() {
        int hash = 1;
        hash = hash * 31 + type.hashCode();
        hash = hash * 31 + name.hashCode();
        return hash;
    }

    /**
     * Compares the given object for the equality with this Event.
     *
     * @param obj the Object to compare with
     * @return true if the given Object is an Event with the same name and type as this one
     *         and false otherwise
     */
    public boolean equals(Object obj) {
        return ((obj instanceof Event) && (obj.hashCode() == hashCode())
                && ((Event) obj).getEventType().equals(type) && ((Event) obj).getName().equals(name));
    }

    /**
     * Returns a string representation of this Event.
     *
     * @return a string representation of this Event
     */
    public String toString() {
        return ToStringUtil.getSimpleName(getClass()) + "[type: " + type + ", name: " + name + ", ctx: " + ctx + "]";
    }
}
